package com.rh.number.service.impl;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.rh.number.common.ApiResult;
import com.rh.number.common.BatchOperationResult;
import com.rh.number.common.FileParseResult;
import com.rh.number.dto.BatchQueryDto;
import com.rh.number.dto.ExcelExportParam;
import com.rh.number.dto.NumberUpdateData;
import com.rh.number.dto.OneNumberUpdateDTO;
import com.rh.number.exception.BusinessException;
import com.rh.number.exception.EmptyResultException;
import com.rh.number.exception.FileParseException;
import com.rh.number.common.PageResult;
import com.rh.number.entity.numberEntity;
import com.rh.number.exception.ResourceNotFoundException;
import com.rh.number.service.NumberService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.rh.number.mapper.NumberMapper ;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Transactional
public class NumberServiceImpl implements NumberService {

    // 配置常量
    private static final int MAX_EXPORT_BATCH_SIZE = 1000;
    private static final String IDS_EMPTY_MSG = "导出ID列表不能为空";
    private static final String EXCEED_MAX_SIZE_MSG = "单次导出最多支持%d条数据";
    private static final String DATA_INCONSISTENCY_MSG = "存在无效ID，缺失数据量：%d";

    private final NumberMapper numberMapper;

    public NumberServiceImpl(NumberMapper numberMapper) {
        this.numberMapper = numberMapper;
    }

    @Override
    public PageResult<numberEntity> selectByCondition(
            numberEntity condition,
            BatchQueryDto batchQuery,
            int pageNum,
            int pageSize
    ) {
        // 分页参数校验
        if (pageSize > 1000) {
            return PageResult.error(400, "单页最多1000条数据");
        }

        // 计算偏移量
        int offset = (pageNum - 1) * pageSize;
        if (offset < 0) offset = 0;

        // 执行查询
        List<numberEntity> data = numberMapper.selectByCondition(
                condition,
                batchQuery,
                pageSize,
                offset
        );

        // 获取总数
        Long total = numberMapper.selectCount(condition, batchQuery);

        // 计算总页数
        int totalPages = (int) Math.ceil((double) total / pageSize);

        return PageResult.success(data, pageNum, pageSize, total, totalPages);
    }
    private static final int MAX_EXPORT_LIMIT = 50000;
    @Override
    @Transactional(
            readOnly = true,
            propagation = Propagation.REQUIRED,
            timeout = 30// 明确指定传播行为
    )
    public List<numberEntity> exportExcel(ExcelExportParam  params) {
        List<numberEntity> data = numberMapper.exportByCondition(params);
        return data;
    }


    private void validatePagination(int pageNum, int pageSize) {
        if (pageNum < 1) {
            throw new IllegalArgumentException("页码不能小于1");
        }
        if (pageSize < 1 || pageSize > 100) {
            throw new IllegalArgumentException("每页数量需在1-100之间");
        }
    }

    @Override
    @Transactional
    public void insert(Number number) {
        numberMapper.insert(number);
    }

    @Override
    @Transactional
    public void batchInsert(List<numberEntity> numbers) {
        if (!numbers.isEmpty()) {
            numberMapper.batchInsert(numbers);
        }
    }


    @Override  // 确保这里添加了@Override注解
    public Set<Long> selectByNum(List<Long> nums) {  // 重点！保持与接口完全一致的返回值类型
        if (nums == null || nums.isEmpty()) {
            return Collections.emptySet();
        }

        // 分批次查询（规避数据库IN语句长度限制）
        Set<Long> result = new HashSet<>();
        int batchSize = 500;

        for (int i = 0; i < nums.size(); i += batchSize) {
            int end = Math.min(i + batchSize, nums.size());
            List<Long> batchList = nums.subList(i, end);

            // 调用Mapper获取本批次存在的号码
            List<Long> existBatch = numberMapper.selectByNum(batchList);
            result.addAll(existBatch);
        }

        return result;
    }
    //导出实现
    @Override
    public List<numberEntity> exportByCondition(numberEntity condition) {
        // 根据条件查询全部数据（不分页）
        return numberMapper.selectByConditions(condition);
    }

    public List<numberEntity> batchQueryByFile(MultipartFile file) throws IOException {
        // 解析文件第一列为 num 列表
        List<String> nums = parseFirstColumn(file);
        return numberMapper.batchQueryByNums(nums);
    }


    //批量查询
    private List<String> parseFirstColumn(MultipartFile file) throws IOException {
        List<String> nums = new ArrayList<>();
        String fileName = file.getOriginalFilename();

        if (fileName.endsWith(".xlsx")) {
            // 解析 Excel 第一列
            EasyExcel.read(file.getInputStream(), new AnalysisEventListener<Map<Integer, String>>() {
                @Override
                public void invoke(Map<Integer, String> row, AnalysisContext context) {
                    String num = row.get(0); // 第一列为 num
                    if (num != null && !num.trim().isEmpty()) {
                        nums.add(num.trim());
                    }
                }
                @Override public void doAfterAllAnalysed(AnalysisContext context) {}
            }).sheet().doRead();

        } else if (fileName.endsWith(".txt")) {
            // 解析 TXT 每行一个 num
            try (BufferedReader reader = new BufferedReader(
                    new InputStreamReader(file.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    if (!line.trim().isEmpty()) {
                        nums.add(line.trim());
                    }
                }
            }
        }
        return nums;
    }

    //批量上架
    @Override
    public BatchOperationResult batchActivate(MultipartFile file)
            throws FileParseException, EmptyResultException {

        try {
            // 解析文件获取客户名称和号码列表
            FileParseResult parseResult = parseFile(file);
            String client = parseResult.getClient();
            List<String> nums = parseResult.getNums();

            // 执行批量更新
            int affectedRows = numberMapper.batchUpdateStatus(
                    nums,
                    "已上架",
                    client,
                    LocalDate.now()
            );

            return new BatchOperationResult(true, "成功更新" + affectedRows + "条记录", nums);

        } catch (FileParseException e) {
            throw new FileParseException("文件解析失败: " + e.getMessage());
        }
    }

    // 文件解析方法（已修改）
    private FileParseResult parseFile(MultipartFile file) throws FileParseException {
        try {
            String filename = file.getOriginalFilename();
            List<String> nums = new ArrayList<>();
            String client = null;

            if (filename.endsWith(".xlsx")) {
                // 解析Excel文件
                List<Map<Integer, String>> excelData = EasyExcel.read(file.getInputStream())
                        .sheet()
                        .headRowNumber(0) // 第一行为客户名称
                        .doReadSync();

                // 获取客户名称（直接读取第一行第一列）
                if (!excelData.isEmpty()) {
                    client = excelData.get(0).get(0).trim();
                }

                // 从第二行开始读取号码
                for (int i = 1; i < excelData.size(); i++) {
                    nums.add(excelData.get(i).get(0).trim());
                }

            } else if (filename.endsWith(".txt")) {
                // 解析TXT文件
                try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(file.getInputStream()))) {

                    // 第一行直接作为客户名称
                    client = reader.readLine();
                    if (client != null) client = client.trim();

                    // 读取后续号码
                    String line;
                    while ((line = reader.readLine()) != null) {
                        if (!line.trim().isEmpty()) {
                            nums.add(line.trim());
                        }
                    }
                }
            } else {
                throw new FileParseException("仅支持 .xlsx 或 .txt 文件");
            }

            // 校验数据有效性
            if (client == null || client.isEmpty()) {
                throw new FileParseException("文件第一行必须填写客户名称");
            }
            if (nums.isEmpty()) {
                throw new FileParseException("文件中没有有效的号码");
            }

            return new FileParseResult(client, nums);

        } catch (IOException | IndexOutOfBoundsException e) {
            throw new FileParseException("文件读取失败: " + e.getMessage());
        }
    }
//    批量下架
@Override
@Transactional(rollbackFor = Exception.class)
public BatchOperationResult batchDeactivate(MultipartFile file)
        throws FileParseException, EmptyResultException {

    try {
        // 解析文件获取号码列表
        List<String> nums = parseFileWithoutClient(file);

        // 执行批量更新
        int affectedRows = numberMapper.batchDeactivate(
                nums,
                "已下架",
                LocalDate.now()
        );

        return new BatchOperationResult(true, "成功下架" + affectedRows + "个号码", nums);
    } catch (FileParseException e) {
        throw new FileParseException("文件解析失败: " + e.getMessage());
    }
}

    /**
     * 解析不含客户名称的文件
     */
    private List<String> parseFileWithoutClient(MultipartFile file) throws FileParseException {
        try {
            String filename = file.getOriginalFilename();
            List<String> nums = new ArrayList<>();

            if (filename.endsWith(".xlsx")) {
                // 解析Excel文件
                List<Map<Integer, String>> excelData = EasyExcel.read(file.getInputStream())
                        .sheet()
                        .headRowNumber(0) // 直接从第一行开始读号码
                        .doReadSync();

                for (Map<Integer, String> row : excelData) {
                    String num = row.get(0);
                    if (num != null && !num.trim().isEmpty()) {
                        nums.add(num.trim());
                    }
                }

            } else if (filename.endsWith(".txt")) {
                // 解析TXT文件
                try (BufferedReader reader = new BufferedReader(
                        new InputStreamReader(file.getInputStream()))) {

                    String line;
                    while ((line = reader.readLine()) != null) {
                        if (!line.trim().isEmpty()) {
                            nums.add(line.trim());
                        }
                    }
                }
            } else {
                throw new FileParseException("仅支持.xlsx和.txt文件");
            }

            if (nums.isEmpty()) {
                throw new FileParseException("文件中没有有效的号码");
            }

            return nums;

        } catch (IOException | IndexOutOfBoundsException e) {
            throw new FileParseException("文件读取失败: " + e.getMessage());
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BatchOperationResult batchUpdate(
            List<Long> ids,
            List<String> nums,
            Map<String, Object> updateFields
    ) {
        // 参数校验
        System.out.println("DEBUG - 更新字段内容: " + updateFields);
        validateParameters(ids, nums, updateFields);

        // 执行更新
        int affectedRows = !ids.isEmpty() ?
                numberMapper.batchUpdateByIds(ids, updateFields) :
                numberMapper.batchUpdateByNums(nums, updateFields);

        return new BatchOperationResult(
                affectedRows > 0,
                "成功更新" + affectedRows + "条记录",
                affectedRows
        );
    }

    // 参数校验
    private void validateParameters(List<Long> ids, List<String> nums, Map<String, Object> fields) {
        // 必须指定 ID 或号码
        if (ids.isEmpty() && nums.isEmpty()) {
            throw new IllegalArgumentException("必须指定要更新的ID或号码");
        }
        // ID 和号码不能同时存在
        if (!ids.isEmpty() && !nums.isEmpty()) {
            throw new IllegalArgumentException("ID和号码不能同时存在");
        }
        // 至少更新一个字段
        if (fields.isEmpty()) {
            throw new IllegalArgumentException("至少指定一个更新字段");
        }
        // 状态字段自动处理时间
        if (fields.containsKey("state")) {
            System.out.println("DEBUG - 进入state条件判断"); // 跟踪点1
            String state = (String) fields.get("state");
            System.out.println("DEBUG - state值: " + state); // 跟踪点2

            if ("已上架".equals(state)) {
                System.out.println("DEBUG - 处理已上架状态"); // 跟踪点3
                fields.put("effectiveDate", LocalDateTime.now());
            } else if ("已下架".equals(state)) {
                System.out.println("DEBUG - 处理已下架状态"); // 跟踪点4
                fields.put("removalTime", LocalDateTime.now());
            } else {
                System.out.println("DEBUG - 未知状态: " + state); // 跟踪点5
            }
        } else {
            System.out.println("DEBUG - fields不包含state字段"); // 跟踪点6
        }
    }

    @Override
    @Transactional
    public void updateNumber(Long id, OneNumberUpdateDTO dto) {
        // 1. 检查记录是否存在
        numberEntity entity = numberMapper.selectById(id);
        if (entity == null) {
            throw new ResourceNotFoundException("ID不存在: " + id);
        }

        // 2. 复制可更新字段
        BeanUtils.copyProperties(dto, entity);

        // 3. 处理状态时间
        handleStateTime(entity, dto.getState());

        // 4. 执行更新
        numberMapper.updateById(entity);
    }

    private void handleStateTime(numberEntity entity, String newState) {
        if ("已上架".equals(newState)) {
            entity.setEffectiveDate(LocalDate.now());
        } else if ("已下架".equals(newState)) {
            entity.setRemovalTime(LocalDate.now());
        }
    }

    @Override
    public List<numberEntity> batchExportByIds(List<Integer> ids)
            throws IllegalArgumentException, BusinessException {

        // 参数基础校验
        validateInput(ids);

        // 执行数据查询
        List<numberEntity> result = numberMapper.selectForExportByIds(ids);

        // 数据完整性校验
        validateResultConsistency(ids, result);

        return result;
    }

    private void validateInput(List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new IllegalArgumentException(IDS_EMPTY_MSG);
        }

        if (ids.size() > MAX_EXPORT_BATCH_SIZE) {
            String message = String.format(EXCEED_MAX_SIZE_MSG, MAX_EXPORT_BATCH_SIZE);
            throw new BusinessException(message);
        }
    }

    private void validateResultConsistency(List<Integer> ids, List<numberEntity> result) {
        int expectedSize = ids.size();
        int actualSize = result.size();

        if (actualSize != expectedSize) {
            int missingCount = expectedSize - actualSize;
            String message = String.format(DATA_INCONSISTENCY_MSG, missingCount);
            throw new BusinessException(message);
        }
    }

    /**
     * 单条删除
     */
    public ApiResult<Void> deleteNumber(Integer id) {
        int count = numberMapper.deleteById(id);
        if (count == 0) {
            return ApiResult.error(404, "记录不存在");
        }
        return ApiResult.success("删除成功");
    }

    /**
     * 批量删除
     */
    public ApiResult<Void> batchDeleteNumbers(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) {
            return ApiResult.error(400, "ID列表不能为空");
        }
        int count = numberMapper.deleteBatchIds(ids);
        return ApiResult.success("成功删除 " + count + " 条记录");
    }

    @Transactional
    public void batchFullUpdate(List<Long> ids, NumberUpdateData updateData) {

        if ("已上架".equals(updateData.getState())) {
            updateData.setEffectiveDate(LocalDate.now());
            updateData.setRemovalTime(null); // 清除无关字段
        } else if ("已下架".equals(updateData.getState())) {
            updateData.setRemovalTime(LocalDate.now());
            updateData.setEffectiveDate(null);
        }
        // 数据校验
        validateUpdateData(updateData);

        // 转换数据
        numberEntity entity = convertToEntity(updateData);

        // 执行更新
        numberMapper.batchFullUpdateByIds(ids, entity);
    }


    @Override
    public ApiResult<?> insertNumber(numberEntity entity) {
        if (numberMapper.existsByNum(entity.getNum())) {
            return ApiResult.error(409, "号码已存在");
        }
        // 执行插入
        int affectedRows = numberMapper.numinsert(entity);
        return affectedRows > 0
                ? ApiResult.success("添加成功")
                : ApiResult.error(500, "数据插入失败");
    }

    private void validateUpdateData(NumberUpdateData data) {
        // 示例校验逻辑
        if (data.getEffectiveDate() != null && data.getEffectiveDate().isAfter(LocalDate.now())) {
            throw new IllegalArgumentException("生效日期不能晚于当前日期");
        }
    }

    private numberEntity convertToEntity(NumberUpdateData data) {
        numberEntity entity = new numberEntity();
        BeanUtils.copyProperties(data, entity);
        return entity;
    }

}


